import 'dart:io';

import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:video_player/video_player.dart';

/// @date 2020/08/27  11:18
/// @author 程志强
/// @des 相机

class CameraRoute extends StatefulWidget {
  @override
  _CameraRouteState createState() => _CameraRouteState();
}

class _CameraRouteState extends State<CameraRoute> with WidgetsBindingObserver {
  // 相机controller
  CameraController _controller;

  // 图片保存路径
  String imagePath;

  // 视频保存路径
  String videoPath;

  // 视频播放controller
  VideoPlayerController _playerController;

  // 视频播放回调
  VoidCallback videoPlayerListener;

  bool enableAudio = true;

// 所有的摄像头
  List<CameraDescription> cameras;

  final GlobalKey<ScaffoldState> _globalKey = GlobalKey<ScaffoldState>();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    getCameras().then((values) => cameras = values);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.inactive) {
      // app 不在前台
      _controller?.dispose();
    } else if (state == AppLifecycleState.resumed) {
      // 前台
      if (_controller != null) {
        onNewCameraSelected(_controller.description);
      }
    }
  }

  // 摄像头选中回调
  void onNewCameraSelected(CameraDescription cameraDescription) async {
    if (_controller != null) {
      await _controller.dispose();
    }

    _controller = CameraController(cameraDescription, ResolutionPreset.high,
        enableAudio: enableAudio);

    _controller.addListener(() {
      if (mounted) setState(() {});

      if (_controller.value.hasError) {
        showInSnackBar('Camera error ${_controller.value.errorDescription}');
      }
    });

    try {
      await _controller.initialize();
    } on CameraException catch (e) {
      _showCameraException(e);
    }

    if (mounted) {
      setState(() {});
    }
  }

  // snack bar 提示信息
  void showInSnackBar(String message) {
    _globalKey.currentState.showSnackBar(SnackBar(content: Text(message)));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _globalKey,
      appBar: AppBar(
        title: Text("相机"),
      ),
      body: Column(
        children: <Widget>[
          _previewContainer(),
          _captureControlRowWidget(),
          _toggleAudioWidget(),
          Padding(
            padding: const EdgeInsets.all(5.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                _cameraTogglesRowWidget(),
                _thumbnailWidget(),
              ],
            ),
          )
        ],
      ),
    );
  }

  // 获取可用摄像头列表，cameras为全局变量
  Future<List<CameraDescription>> getCameras() async {
    return await availableCameras();
  }

  // 预览
  Widget _previewContainer() {
    return Expanded(
      child: Container(
        child: Padding(
          padding: const EdgeInsets.all(1.0),
          child: _cameraPreviewWidget(),
        ),
        decoration: BoxDecoration(
          color: Colors.black,
          border: Border.all(
              color: _controller != null && _controller.value.isRecordingVideo
                  ? Colors.redAccent
                  : Colors.grey,
              width: 3.0),
        ),
      ),
    );
  }

  // 相机工具

  Widget _captureControlRowWidget() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      mainAxisSize: MainAxisSize.max,
      children: <Widget>[
        IconButton(
          icon: const Icon(Icons.camera_alt),
          color: Colors.blue,
          onPressed: _controller != null && !_controller.value.isRecordingVideo
              ? onTakePictureButtonPressed
              : null,
        ),
        IconButton(
          icon: const Icon(Icons.video_call),
          color: Colors.blue,
          onPressed: _controller != null &&
              _controller.value.isInitialized &&
              !_controller.value.isRecordingVideo
              ? onVideoRecordButtonPressed
              : null,
        ),
        IconButton(
          icon: const Icon(Icons.stop),
          color: Colors.red,
          onPressed: _controller != null &&
              _controller.value.isInitialized &&
              _controller.value.isRecordingVideo
              ? onStopButtonPressed
              : null,
        ),
      ],
    );
  }

  // 开启或关闭录取
  Widget _toggleAudioWidget() {
    return Padding(
      padding: const EdgeInsets.only(left: 25.0),
      child: Row(
        children: <Widget>[
          const Text("开启录音"),
          Switch(
            value: enableAudio,
            onChanged: (val) {
              enableAudio = val;
              if (_controller != null) {
                onNewCameraSelected(_controller.description);
              }
            },
          )
        ],
      ),
    );
  }

  // 展示所有摄像头
  Widget _cameraTogglesRowWidget() {
    final List<Widget> toggles = <Widget>[];
    if (null == cameras || cameras.isEmpty) {
      return const Text("没有检测到摄像头");
    } else {
      for (var val in cameras) {
        toggles.add(SizedBox(
          width: 90.0,
          child: RadioListTile<CameraDescription>(
            title: Icon(getCameraLensIcon(val.lensDirection)),
            groupValue: _controller?.description,
            value: val,
            onChanged: _controller != null && _controller.value.isRecordingVideo
                ? null
                : onNewCameraSelected,
          ),
        ));
      }
    }
    return Row(children: toggles);
  }

  /// 获取不同摄像头的图标（前置、后置、其它）
  IconData getCameraLensIcon(CameraLensDirection direction) {
    switch (direction) {
      case CameraLensDirection.back:
        return Icons.camera_rear;
      case CameraLensDirection.front:
        return Icons.camera_front;
      case CameraLensDirection.external:
        return Icons.camera;
    }
    throw ArgumentError('Unknown lens direction');
  }

  /// 显示已拍摄的图片/视频缩略图。
  Widget _thumbnailWidget() {
    return Expanded(
      child: Align(
        alignment: Alignment.centerRight,
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            _playerController == null && imagePath == null
                ? Container()
                : SizedBox(
              child: (_playerController == null)
                  ? Image.file(File(imagePath))
                  : Container(
                child: Center(
                  child: AspectRatio(
                      aspectRatio:
                      _playerController.value.size != null
                          ? _playerController.value.aspectRatio
                          : 1.0,
                      child: VideoPlayer(_playerController)),
                ),
                decoration: BoxDecoration(
                    border: Border.all(color: Colors.pink)),
              ),
              width: 64.0,
              height: 64.0,
            ),
          ],
        ),
      ),
    );
  }

  // 拍照按钮回调
  onTakePictureButtonPressed() {
    takePicture().then((value) {
      if (mounted) {
        setState(() {
          imagePath = value;
          _playerController?.dispose();
          _playerController = null;
        });
        if (value != null) showInSnackBar("图片保存在$value}");
      }
    });
  }

  // 开始录制视频
  onVideoRecordButtonPressed() {
    startVideoRecording().then((value) {
      if (mounted) {
        setState(() {});
      }
      if (value != null) showInSnackBar("正在录制视频于:$value");
    });
  }

  //停止视频录制
  onStopButtonPressed() {
    stopVideoRecording().then((_) {
      if (mounted) setState(() {});
      showInSnackBar('视频保存在: $videoPath');
    });
  }

  // 展示预览窗口
  Widget _cameraPreviewWidget() {
    if (_controller == null || !_controller.value.isInitialized) {
      return const Text(
        "选择一个摄像头",
        style: TextStyle(
            color: Colors.white, fontSize: 24.0, fontWeight: FontWeight.w900),
      );
    } else {
      return AspectRatio(
        aspectRatio: _controller.value.aspectRatio,
        child: CameraPreview(_controller),
      );
    }
  }

  // 时间戳
  String timestamp() =>
      DateTime
          .now()
          .millisecondsSinceEpoch
          .toString();

  // 拍照
  Future<String> takePicture() async {
    if (!_controller.value.isInitialized) {
      showInSnackBar("错误，请选择一个相机");
      return null;
    }
    final Directory extDir = await getApplicationDocumentsDirectory();
    final String dirPath = "${extDir.path}/Pictures/flutter_test";
    await Directory(dirPath).create(recursive: true);
    final String filePath = "$dirPath/${timestamp()}.jpg";
    // 正在录制视频
    if (_controller.value.isRecordingVideo) {
      return null;
    }
    try {
      videoPath = filePath;
      await _controller.startVideoRecording();
    } catch (e) {
      _showCameraException(e);
      return null;
    }
    return filePath;
  }

  // 录制视频
  Future<String> startVideoRecording() async {
    if (!_controller.value.isInitialized) {
      showInSnackBar("请选择一个摄像头");
      return null;
    }
    final Directory extDir = await getApplicationDocumentsDirectory();
    final String dirPath = "${extDir.path}/Movies/flutter_test";
    await Directory(dirPath).create(recursive: true);
    final String filePath = "$dirPath/${timestamp()}.mp4";
    // 正在录制
    if (_controller.value.isRecordingVideo) {
      return null;
    }

    try {
      videoPath = filePath;
      await _controller.startVideoRecording();
    } catch (e) {
      _showCameraException(e);
      return null;
    }
    return filePath;
  }

  // 停止录制视频
  Future<void> stopVideoRecording() async {
    if (!_controller.value.isRecordingVideo) {
      return null;
    }
    try {
      await _controller.stopVideoRecording();
    } catch (e) {
      _showCameraException(e);
      return null;
    }
    // 开始播放
    await _startVideoPlayer();
  }

  // 开始播放
  Future<void> _startVideoPlayer() async {
    final VideoPlayerController vpController =
    VideoPlayerController.file(File(videoPath));

    videoPlayerListener = () {
      if (_playerController != null && _playerController.value.size != null) {
        if (mounted) {
          setState(() {});
        }
        _playerController.removeListener(videoPlayerListener);
      }
    };

    vpController.addListener(videoPlayerListener);

    await vpController.setLooping(true);
    await vpController.initialize();
    await vpController?.dispose();
    if (mounted) {
      setState(() {
        imagePath = null;
        _playerController = vpController;
      });
    }
    await vpController.play();
  }

  // 打印日志
  void logError(String code, String message) =>
      print("Error:$code\nError Message :$message}");

  // 异常信息
  _showCameraException(CameraException e) {
    logError(e.code, e.description);
    showInSnackBar("Error:${e.code} \n ${e.description}");
  }
}
